<!--
Date: 2025-08-13
Copyright (c) 2025 Industrial Software Feature Database
-->
<template>
  <el-dialog v-if="props.dialogVisible" v-model="props.dialogVisible" title="重新上传" width="600px" append-to-body :before-close="closeDialog">
    <div v-loading="loading">
      <div class="model-batch">
        <label for="">机型：</label><span style="margin-right: 20px;">{{ props.row?.modelNumber }}</span>
        <label for="">批次：</label><span style="margin-right: 20px;">{{ props.row?.batchNumber }}</span>
        <label for="">轮次：</label><span style="margin-right: 20px;">{{ props.row?.roundNumber }}</span><br>
        <label for="">适用部段：</label><span style="margin-right: 20px;">{{ props.row?.sectionNumbersString }}</span>
        <label for="">备注：</label><span>{{ props.row?.remarks }}</span>
      </div>
      <el-upload 
        class="upload-demo" 
        style="width:480px;" 
        :limit="1"
        drag 
        :beforeUpload="beforeUpload" 
        :on-change="handleChange"
        :on-success="handleSuccess"
        :on-error="handleError"
        :http-request="componentImport"
        accept=".op2,.h5">
        <el-icon class="el-icon--upload"><upload-filled /></el-icon>
        <div class="el-upload__text" style="text-align: center;">
          点击或将文件拖拽到这里上传<br>
          1.只支持.op2文件上传。<br>
          2.支持多文件同时上传。<br>
        </div>
      </el-upload>
    </div>
    <template #footer>
      <div class="dialog-footer" style="text-align: center;">
        <el-button @click="closeDialog">取消</el-button>
        <el-button type="primary" @click="reUploadFile">确定上传</el-button>
      </div>
    </template>
    
  </el-dialog>
  <el-dialog v-model="dialogFormVisible" title="文件努力上传中，请耐心等待..." width="500" :show-close="false">
      <div class="upload-list">
        <div 
          class="file-item"
        >
          <div class="file-info">
            <span class="filename">{{ loadFile.fileName }}</span>
            <span class="size">{{ formatSize(loadFile.fileSize) }}</span>
          </div>
          
          <div class="progress-container">
            <div 
              class="progress-bar" 
              :style="{ width: `${loadFile.progress}%` }"
            ></div>
            <span class="progress-text">{{ Math.floor(loadFile.progress) }}%</span>
          </div>
        </div>
      </div>
    </el-dialog>
</template>

<script setup name="Op2ReUpload">
import { getToken } from '@/utils/auth';
import { getAllFileList, checkOp2ChunksUploadProgress, op2ChunksUploadAgain } from '@/api/dataAcquisition';
import { calculateHash } from './generateHash.js';
const emit = defineEmits(['handleEvent']);
const loading = ref(false);
const props = defineProps(['row', 'dialogVisible']);
const CHUNK_SIZE = 10 * 1024 * 1024; // 切片
const dialogFormVisible = ref(false);
const MAX_CONCURRENT = 10;
const MAX_WORKERS = 10;
const THREAD_COUNT = navigator.hardwareConcurrency || 4;
const treeData = ref([]);
const modelNumber = ref('');
const batchNumber = ref('');
const uploadFile = ref();
const primaryHash = ref('');
const uploadId = ref('');
const currentHash = ref('');
const existChunks = ref([]);
const loadFile = ref({});
const finalFileSuffix = ref('');
const closeDialog = () => {
  emit('handleEvent', {type: 'cancel'});
};
// 工具函数：格式化文件大小
const formatSize = (bytes) => {
  const units = ['B', 'KB', 'MB', 'GB']
  let size = bytes
  let unitIndex = 0
  while (size >= 1024 && unitIndex < units.length - 1) {
    size /= 1024
    unitIndex++
  }
  return `${size.toFixed(1)} ${units[unitIndex]}`
}
const reUploadFile = async () => {
  loading.value = true;
  currentHash.value = await calculateHash(uploadFile.value.raw, CHUNK_SIZE);
  loading.value = false;
  // console.log(String(primaryHash.value) == String(currentHash.value), primaryHash.value,currentHash.value)
  if (primaryHash.value == currentHash.value) {
    // check已上传切片
    checkOp2ChunksUploadProgress({
      fileHash: currentHash.value,
      uploadId: uploadId.value
    }).then(res => {
      const progress = 100 * res.data.existChunks.length / props.row.isfdLargeFileVo.totalChunks;
      existChunks.value = res.data.existChunks;
      loadFile.value = {
        fileName: props.row.isfdLargeFileVo.fileName,
        fileSize: props.row.isfdLargeFileVo.fileSize,
        chunkSize: CHUNK_SIZE,
        progress: progress,
        "fileSuffix": finalFileSuffix.value,
        file: uploadFile.value,
        fileHash: currentHash.value,
        uploadId: props.row.isfdLargeFileVo.uploadId,
        totalChunks: props.row.isfdLargeFileVo.totalChunks,
        uploadedChunks: new Set(existChunks.value),
        existChunks: existChunks.value
      }
      dialogFormVisible.value = true;
      doUpload();
    })
  } else {
    // 上传新的文件
    let fileParam = {
      fileName: uploadFile.value.name,
      fileSize: uploadFile.value.size,
      chunkSize: CHUNK_SIZE,
      progress: 0,
      "fileSuffix": finalFileSuffix.value,
      file: uploadFile.value,
      fileHash: currentHash.value
    }
    let params = {
      id: props.row.id,
      originalFileHash: primaryHash.value,
      largeFileBoList: [
        fileParam
      ]
    }
    op2ChunksUploadAgain(params).then(res => {
      const { uploadId, existChunks, totalChunks, chunkIndex, fileUrl } = res.data[0];
      loadFile.value = {
        fileName: uploadFile.value.name,
        fileSize: uploadFile.value.size,
        chunkSize: CHUNK_SIZE,
        progress: 0,
        "fileSuffix": finalFileSuffix.value,
        file: uploadFile.value,
        fileHash: currentHash.value,
        uploadId: uploadId,
        totalChunks: totalChunks,
        uploadedChunks: new Set(existChunks || []),
        existChunks: existChunks,
        fileUrl: fileUrl
      }
      if (fileUrl) {
        // 存在这个文件 不用重复上传
        emit('handleEvent', {type: 'refresh'});
      } else {
        dialogFormVisible.value = true;
        doUpload();
      }
    })
  }
}
const doUpload = () => {
  const chunks = Array.from({ length: Math.ceil(loadFile.value.file.size / CHUNK_SIZE) }, (_, i) =>
    loadFile.value.file.raw.slice(i * CHUNK_SIZE, (i + 1) * CHUNK_SIZE)
  )
  loadFile.value.chunks = chunks;
  startUpload();
}
// 全部上传成功跳转完成
const checkAllFileUploadSuccess = () => {
  return loadFile.value.totalChunks == loadFile.value.uploadedChunks.size
}
const startUpload = () => {
  // files.forEach((file) => {
    const chunkCount = Math.ceil(loadFile.value.fileSize / CHUNK_SIZE);  // 300 / 10
    const threadChunkCount = Math.ceil(chunkCount / THREAD_COUNT); // 30 / 4 每个进程操作切片个数 8 
     
    for (let i = 0; i < THREAD_COUNT; i ++) {
      // 开启一个线程任务 
      const worker = new Worker(new URL('./upload.worker.js', import.meta.url), {
        type: 'module'
      })
      let start = i * threadChunkCount;
      let end = Math.min(start + threadChunkCount, chunkCount);
      
      worker.postMessage({
        type: 'START_UPLOAD',
        payload: {
          file: toRaw(loadFile.value.file), //toRaw(_file),
          fileHash: loadFile.value.fileHash,
          start: start,
          chunks: loadFile.value.chunks.slice(start, end).map(c => toRaw(c)),
          uploadId: loadFile.value.uploadId,
          chunkSize: CHUNK_SIZE,
          uploadedChunks: Array.from(toRaw(loadFile.value.uploadedChunks)),
          token: getToken()
        }
      })

      worker.onmessage = (e) => {
        const { type, payload } = e.data
        switch (type) {
          case 'PROGRESS':
            loadFile.value.progress = 100 * Number(loadFile.value.uploadedChunks.size || 0) / loadFile.value.totalChunks;
            break
          case 'CHUNK_DONE':
            loadFile.value.uploadedChunks.add(payload.index)
            loadFile.value.progress = 100 * Number(loadFile.value.uploadedChunks.size || 0) / loadFile.value.totalChunks;
            if (checkAllFileUploadSuccess()) {
              // active.value ++;
              dialogFormVisible.value = false;
              emit('handleEvent', {type: 'refresh'});
            }
            break
          case 'COMPLETE':
            console.log('上传完成:', payload)
            worker.terminate()
            break
          case 'ERROR':
            console.error('上传错误:', payload)
            break
        }
      }
    }
  // })
}

const handleChange = async (file) => {
  // uploadFiles.value = fileList;
  uploadFile.value = file;
  
};
const handleSuccess = (response, file, fileList) => {};
const handleError = (error, file, fileList) => {};
// 验证文件格式是否正确
const beforeUpload = (file) => {
  let fileSuffix = file.name.split('.')[file.name.split('.').length - 1];
  finalFileSuffix.value = fileSuffix;
  let isFile = fileSuffix == 'op2' || fileSuffix == 'h5';
  if (!isFile) {
    ElMessage.error('导入文件格式不正确');
    return false;
  }
};
// 读取压缩文件
const componentImport = async (file, fileList) => {};
onMounted(() => {
  primaryHash.value = props.row.isfdLargeFileVo.fileHash;
  uploadId.value = props.row.isfdLargeFileVo.uploadId;
});
</script>

<style lang="scss" scoped>
@import './op2.scss';
.model-batch {
  padding: 10px;
  span {
    margin-right: 20px;
  }
}
</style>
